﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using DirectShowLib;
using System.Runtime.InteropServices;

namespace DxSnap
{
	public partial class DeviceOption : Form
	{
		//IBaseFilter theDevice = null;
		#region API
		[DllImport("oleaut32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
		public static extern int OleCreatePropertyFrame(
			IntPtr hwndOwner,
			int x,
			int y,
			[MarshalAs(UnmanagedType.LPWStr)] string lpszCaption,
			int cObjects,
			[MarshalAs(UnmanagedType.Interface, ArraySubType = UnmanagedType.IUnknown)] 
			ref object ppUnk,
			int cPages,
			IntPtr lpPageClsID,
			int lcid,
			int dwReserved,
			IntPtr lpvReserved);

		#endregion

		public DeviceOption()
		{
			InitializeComponent();
		}

		private void DeviceOption_Load(object sender, EventArgs e)
		{
			//frame size
			string[] frmSizeArray = new string[] { "160 x 120", "320 x 240", "640 x 480", "1024 x 768", "2048 x 1536" };
			foreach (string sz in frmSizeArray)
			{
				comboBox2.Items.Add(sz);
			}
			this.comboBox2.SelectedIndex = 2;

			//frame rate (8fps @ 2048x1536 40fps @ 640x480 24fps @ 1024x768)

			string[] frmRateArray = new string[] { "8 fps (md300 2048x1536)", "15 fps", "24 fps (md300 1024x768)", "25 fps (PAL)", "29.997 fps (NTSC)", "30 fps (~NTSC)", "40 fps (md300 640x480)", "59.994 fps (2xNTSC)" };
			foreach (string rt in frmRateArray)
			{
				comboBox3.Items.Add(rt);
			}
			this.comboBox3.SelectedIndex = 2;

			//device
			foreach (DsDevice ds in DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice))
			{
				this.listBox1.Items.Add(ds.Name);
			}
			if(this.listBox1.Items.Count > 0)
				this.listBox1.SelectedIndex = 0;

			this.listBox1.Focus();
		}

		private void button1_Click(object sender, EventArgs e)
		{
			if (this.listBox1.SelectedIndex < 0)
			{
				MessageBox.Show("请选择一个设备");
				return;
			}

			//device index
			DeviceSettings.Default.VIDEODEVICE = this.listBox1.SelectedIndex;

			//frame size
			switch (this.comboBox2.SelectedIndex)
			{
				case 0:
					DeviceSettings.Default.VIDEOWIDTH = 160;
					DeviceSettings.Default.VIDEOHEIGHT = 120;
					break;
				case 1:
					DeviceSettings.Default.VIDEOWIDTH = 320;
					DeviceSettings.Default.VIDEOHEIGHT = 240;
					break;
				case 2:
					DeviceSettings.Default.VIDEOWIDTH = 640;
					DeviceSettings.Default.VIDEOHEIGHT = 480;
					break;
				case 3:
					DeviceSettings.Default.VIDEOWIDTH = 1024;
					DeviceSettings.Default.VIDEOHEIGHT = 768;
					break;
				case 4:
					DeviceSettings.Default.VIDEOWIDTH = 2048;
					DeviceSettings.Default.VIDEOHEIGHT = 1536;
					break;
			}

			//frame rate


			//bpp
			DeviceSettings.Default.VIDEOBITSPERPIXEL = Convert.ToInt16(this.textBox1.Text);

			DeviceSettings.Default.Save();
			this.DialogResult = DialogResult.OK;
		}

		private void button3_Click(object sender, EventArgs e)
		{
			string devicepath = this.listBox1.SelectedItem.ToString();
			IBaseFilter theDevice = CreateFilter(FilterCategory.VideoInputDevice, devicepath);

			DisplayPropertyPage(theDevice);
		}

		private IBaseFilter CreateFilter(Guid category, string friendlyname)
		{
			object source = null;
			Guid iid = typeof(IBaseFilter).GUID;
			foreach (DsDevice device in DsDevice.GetDevicesOfCat(category))
			{
				if (device.Name.CompareTo(friendlyname) == 0)
				{
					device.Mon.BindToObject(null, null, ref iid, out source);
					break;
				}
			}

			return (IBaseFilter)source;
		}

		/// <summary>
		/// Displays a property page for a filter
		/// </summary>
		/// <param name="dev">The filter for which to display a property page</param>
		private void DisplayPropertyPage(IBaseFilter dev)
		{
			//Get the ISpecifyPropertyPages for the filter
			ISpecifyPropertyPages pProp = dev as ISpecifyPropertyPages;
			int hr = 0;

			if (pProp == null)
			{
				//If the filter doesn't implement ISpecifyPropertyPages, try displaying IAMVfwCompressDialogs instead!
				IAMVfwCompressDialogs compressDialog = dev as IAMVfwCompressDialogs;
				if (compressDialog != null)
				{

					hr = compressDialog.ShowDialog(VfwCompressDialogs.Config, IntPtr.Zero);
					DsError.ThrowExceptionForHR(hr);
				}
				return;
			}

			//Get the name of the filter from the FilterInfo struct
			FilterInfo filterInfo;
			hr = dev.QueryFilterInfo(out filterInfo);
			DsError.ThrowExceptionForHR(hr);

			// Get the propertypages from the property bag
			DsCAUUID caGUID;
			hr = pProp.GetPages(out caGUID);
			DsError.ThrowExceptionForHR(hr);

			// Create and display the OlePropertyFrame
			object oDevice = (object)dev;
			hr = OleCreatePropertyFrame(this.Handle, 0, 0, filterInfo.achName, 1, ref oDevice, caGUID.cElems, caGUID.pElems, 0, 0, IntPtr.Zero);
			DsError.ThrowExceptionForHR(hr);

			// Release COM objects
			Marshal.FreeCoTaskMem(caGUID.pElems);
			Marshal.ReleaseComObject(pProp);
			if (filterInfo.pGraph != null)
			{
				Marshal.ReleaseComObject(filterInfo.pGraph);
			}
		}
	}
}
